package test;

import java.util.List;
import java.util.concurrent.ExecutionException;

import javax.swing.SwingWorker;

import myAsm.MyFieldInsnNode;
import myAsm.MyFrameNode;
import myAsm.MyIincInsnNode;
import myAsm.MyInsnNode;
import myAsm.MyIntInsnNode;
import myAsm.MyJumpInsnNode;
import myAsm.MyLabelNode;
import myAsm.MyLdcInsnNode;
import myAsm.MyLineNumberNode;
import myAsm.MyLookupSwitchInsnNode;
import myAsm.MyMethodInsnNode;
import myAsm.MyMultiANewArrayInsnNode;
import myAsm.MyTableSwitchInsnNode;
import myAsm.MyTypeInsnNode;
import myAsm.MyVarInsnNode;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.objectweb.asm.Opcodes;

import MVC.Exceptions.CPException;

/**
 * @author pichots
 *
 */
public abstract class SuperPatternFinder extends SwingWorker<methodResult, Void> implements PatternFinder,Opcodes{
	
	

	/**
     * The name of the method you want to check
     */
	private String methodID;

	
	public SuperPatternFinder(){
        this.methodID = "";	
	}
	
	
	/**
	 * @param nomClasse 
	 * @param nomMethode
	 */
	public SuperPatternFinder(String IDMethode){
        this.methodID = IDMethode;	
	}
	
	
	
	/**
	 * @return an ArrayList containing all the {@link MyFieldInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyFieldInsnNode> getFieldInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Field:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_FIELD'");
		query.addEntity(MyFieldInsnNode.class);
		List<MyFieldInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyFrameNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyFrameNode> getFrameNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Frame:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_FRAME'");
		query.addEntity(MyFrameNode.class);
		List<MyFrameNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyIincInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyIincInsnNode> getIincInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Iinc:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_IINC'");
	//	SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_IINC'");
		query.addEntity(MyIincInsnNode.class);
		List<MyIincInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyInsnNode> getInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Insn:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_INSNNODE'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_INSNNODE'");
		query.addEntity(MyInsnNode.class);
		List<MyInsnNode> liste =query.list();
		//System.out.println(liste.size());
		/*for(int j = 0; j<liste.size(); j++ ){
			System.out.println(liste.get(j).getOpcode());
		}*/
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyIntInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyIntInsnNode> getIntInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Int:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_INTINSN'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_INTINSN'");
		query.addEntity(MyIntInsnNode.class);
		List<MyIntInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyJumpInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyJumpInsnNode> getJumpInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Jump:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_JUMP'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_JUMP'");
		query.addEntity(MyJumpInsnNode.class);
		List<MyJumpInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyLabelNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyLabelNode> getLabelNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Label:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_LABELNODE'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_LABELNODE'");
		query.addEntity(MyLabelNode.class);
		List<MyLabelNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyLdcInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyLdcInsnNode> getLdcInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("LdcInsnNode:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_LDC'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_LDC'");
		query.addEntity(MyLdcInsnNode.class);
		List<MyLdcInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyLineNumberNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyLineNumberNode> getLineNumberNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("LineNumber:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_LINENUMBER'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_LINENUMBER'");
		query.addEntity(MyLineNumberNode.class);
		List<MyLineNumberNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyLookupSwitchInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyLookupSwitchInsnNode> getLookUpSwitchInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("LookupSwitch:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_LOOKUPSWITCH'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_LOOKUPSWITCH'");
		query.addEntity(MyLookupSwitchInsnNode.class);
		List<MyLookupSwitchInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyMethodInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyMethodInsnNode> getMethodInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Method:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_METHOD'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_METHOD'");
		query.addEntity(MyMethodInsnNode.class);
		List<MyMethodInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyMultiANewArrayInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyMultiANewArrayInsnNode> getMultiANewArrayInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("MultiANewArray:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_MULTIANEWARRAY'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_MULTIANEWARRAY'");
		query.addEntity(MyMultiANewArrayInsnNode.class);
		List<MyMultiANewArrayInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyTableSwitchInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyTableSwitchInsnNode> getTableSwitchInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("TableSwitch:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_TABLESWITCH'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_TABLESWITCH'");
		query.addEntity(MyTableSwitchInsnNode.class);
		List<MyTableSwitchInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyTypeInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyTypeInsnNode> getTypeInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Type:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_TYPE'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_TYPE'");
		query.addEntity(MyTypeInsnNode.class);
		List<MyTypeInsnNode> liste =query.list();
		//System.out.println(liste.size());
		s.close();
		return liste;
	}


	/**
	 * @return an ArrayList containing all the {@link MyVarInsnNode} 
	 * of the method this.methodID from the class className
	 */
	public List<MyVarInsnNode> getVarInsnNode() {
		Session s = HibernateUtils.getSession();
		//System.out.println("Var:");
		SQLQuery query = s.createSQLQuery("SELECT * FROM mtd_method  m INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE MTD_ID = '"+this.methodID+"' AND INSN='INSN_VAR'");
		//SQLQuery query = s.createSQLQuery("SELECT * FROM cls_class  c INNER JOIN cls_class_mtd_method cm ON (c.CLS_ID = cm.CLS_CLASS_CLS_ID) INNER JOIN mtd_method m ON (m.MTD_ID = cm.methods_MTD_ID) INNER JOIN mtd_method_insn_instructions mi ON (m.MTD_ID = mi.MTD_METHOD_MTD_ID) INNER JOIN insn_instructions i ON (mi.instructions_INSN_ID = i.INSN_ID) WHERE CLS_NAME = '"+className+"' AND MTD_NAME = '"+this.methodID+"' AND INSN='INSN_VAR'");
		query.addEntity(MyVarInsnNode.class);
		List<MyVarInsnNode> liste =query.list();
		//System.out.println(liste.size());
		/*s.createCriteria(MyVarInsnNode.class). createCriteria("MTD_METHOD_MTD_ID", (Integer) IDM.get(i)).list();*/
		s.close();
		return liste;
	}



	@Override
	protected methodResult doInBackground() throws CPException {
		return checkPattern();
	}
	
	@Override
	public methodResult executeCheckPattern() throws CPException{
		//System.out.println("Execute check pattern");
		execute();
		try {
			return get();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		
	}
	

	
}
